	SUBROUTINE GETCFMNG ( LUNIT, NEMOI, IVALI, NEMOD, IVALD,
     .			      CMEANG, LNMNG, IRET )

C*$$$  SUBPROGRAM DOCUMENTATION BLOCK
C
C SUBPROGRAM:    GETCFMNG
C   PRGMMR: ATOR             ORG: NCEP       DATE: 2018-01-11
C
C ABSTRACT:  THIS ROUTINE CAN BE CALLED AT ANY TIME AFTER A BUFR MESSAGE
C   HAS BEEN READ INTO MEMORY VIA SUBROUTINE READMG, READERME OR
C   EQUIVALENT, AND IT CAN BE CALLED FOR ANY CODE OR FLAG TABLE MNEMONIC
C   DEFINED WITHIN THAT MESSAGE.  IT SEARCHES FOR THE SPECIFIED MNEMONIC
C   AND ASSOCIATED VALUE (CODE FIGURE OR BIT NUMBER) WITHIN THE INTERNAL
C   MEMORY STRUCTURE FOR STORING CODE/FLAG TABLE INFORMATION, AND IF
C   FOUND RETURNS THE ASSOCIATED MEANING AS A CHARACTER STRING.  THE
C   SEARCH MAY ALSO OPTIONALLY INCLUDE A SPECIFIED SECOND MNEMONIC
C   AND ASSOCIATED VALUE UPON WHICH THE FIRST MNEMONIC AND ITS
C   ASSOCIATED VALUE DEPEND, FOR CASES SUCH AS, E.G. WHEN THE MEANING
C   OF AN ORIGINATING SUBCENTER VALUE DEPENDS ON THE IDENTITY OF THE
C   ORIGINATING CENTER.
C
C   NOTE THAT THIS ROUTINE CAN ONLY BE CALLED FOR MNEMONICS WHICH ARE
C   DEFINED WITHIN THE MESSAGE THAT WAS MOST RECENTLY READ INTO MEMORY.
C   IN MOST CASES THIS MEANS THAT THE MNEMONIC MUST BE CONTAINED WITHIN
C   THE SUBSET DEFINITION (SECTION 3) OF THAT MESSAGE.  THE ONLY
C   EXCEPTIONS TO THIS RULE ARE FOR ORIGINATING CENTERS, ORIGINATING
C   SUBCENTERS, DATA TYPES AND DATA SUBTYPES, SINCE THOSE CAN ALSO BE
C   CONTAINED WITHIN THE IDENTIFICATION SECTION (SECTION 1) OF A BUFR
C   MESSAGE.  IN ANY CASE, IF THE SEARCH IS UNSUCCESSFUL, AND IF THERE
C   WAS NO OPTIONAL SECOND MNEMONIC AND ASSOCIATED VALUE SPECIFIED ON
C   INPUT, THE ROUTINE WILL RE-SEARCH THE TABLE TO CHECK WHETHER THE
C   MEANING OF THE FIRST MNEMONIC AND ASSOCIATED VALUE MAY INDEED DEPEND
C   ON THE VALUE OF ONE OR MORE OTHER POSSIBLE SECOND MNEMONICS.  IF SO,
C   THOSE POSSIBLE MNEMONICS ARE RETURNED ALONG WITH A SPECIAL RETURN
C   CODE SO THAT THE CALLING ROUTINE MAY EXAMINE THEM AND POSSIBLY ISSUE
C   ANOTHER SUBSEQUENT CALL TO THIS SAME ROUTINE WITH SPECIFIED VALUES
C   FOR THE SECOND MNEMONIC AND ASSOCIATED VALUE.
C
C PROGRAM HISTORY LOG:
C 2018-01-11  J. ATOR    -- ORIGINAL AUTHOR
C 2018-01-11  J. ATOR    -- ADD SPECIAL HANDLING FOR DATA TYPES AND
C                           SUBTYPES IN SECTION 1
C
C USAGE:   CALL GETCFMNG ( LUNIT, NEMOI, IVALI, NEMOD, IVALD,
C                          CMEANG, LNMNG, IRET )
C
C   INPUT ARGUMENT LIST:
C     LUNIT    - INTEGER: FORTRAN LOGICAL UNIT NUMBER FOR BUFR FILE
C     NEMOI    - CHARACTER*(*): MNEMONIC TO SEARCH FOR
C     IVALI    - INTEGER: VALUE (CODE FIGURE OR BIT NUMBER) ASSOCIATED
C                WITH NEMOI
C     NEMOD    - CHARACTER*(*): OPTIONAL SECOND MNEMONIC UPON WHICH THE
C                VALUES NEMOI AND IVALI DEPEND; SET TO ALL BLANK
C                CHARACTERS IF THE MEANINGS OF NEMOI AND IVALI DO NOT
C                DEPEND ON THE VALUE OF ANY OTHER MNEMONIC
C     IVALD    - INTEGER: VALUE (CODE FIGURE OR BIT NUMBER) ASSOCIATED
C                WITH NEMOD; SET TO (-1) WHENEVER NEMOD IS SET TO ALL
C                BLANK CHARACTERS
C
C   OUTPUT ARGUMENT LIST:
C     CMEANG   - CHARACTER*(*): IF THE INITIAL SEARCH OF THE TABLE WAS
C                SUCCESSFUL, THEN THIS STRING CONTAINS THE MEANING
C                CORRESPONDING TO NEMOI AND IVALI (AND TO NEMOD AND
C                IVALD, IF SPECIFIED).  HOWEVER, IF THE INITIAL SEARCH
C                WAS UNSUCCESSFUL, *AND* IF NO OPTIONAL SECOND MNEMONIC
C                AND ASSOCIATED VALUE WERE SPECIFIED ON INPUT, *AND* IF
C                THE SECOND SEARCH OF THE TABLE DETERMINED THAT THE
C                MEANING OF THE FIRST MNEMONIC AND ASSOCIATED VALUE
C                INDEED DEPENDS ON ONE OR MORE OTHER POSSIBLE SECOND
C                MNEMONICS, THEN THOSE POSSIBLE SECOND MNEMONICS
C                ARE RETURNED WITHIN THIS STRING, AS A SERIES OF IRET
C                SUCCESSIVE 8-BYTE SUBSTRINGS 
C     LNMNG    - INTEGER: LENGTH OF STRING RETURNED IN MEANING
C     IRET     - RETURN CODE:
C                   0 = MEANING FOUND AND STORED IN CMEANG STRING
C                  -1 = MEANING NOT FOUND
C                  >0 = MEANING NOT FOUND, *AND* NEMOD AND IVALD WERE
C                       NOT SPECIFIED ON INPUT, *AND* THE MEANING OF
C                       NEMOI AND IVALI DEPENDS ON THE VALUE OF ONE OF
C                       THE MNEMONICS STORED IN THE FIRST IRET 8-BYTE
C                       SUBSTRINGS OF THE CMEANG STRING 
C
C REMARKS:
C    THIS ROUTINE CALLS:        BORT     IFXY     IREADMT  NEMTAB
C                               NUMTBD   PARSTR   SRCHTBF  STATUS
C    THIS ROUTINE IS CALLED BY: None
C                               Normally called only by application
C                               programs.
C
C ATTRIBUTES:
C   LANGUAGE: FORTRAN
C   MACHINE:  PORTABLE TO ALL PLATFORMS
C
C$$$

	USE MODA_TABABD

	INCLUDE 'bufrlib.prm'

	COMMON /TABLEF/ CDMF

	CHARACTER*(*)	NEMOI, NEMOD, CMEANG

	CHARACTER*128	BORT_STR
	CHARACTER*8	NEMO
	CHARACTER*1	CDMF, TAB

	DIMENSION	IFXYD(10)

C-----------------------------------------------------------------------
C-----------------------------------------------------------------------

	CALL STATUS ( LUNIT, LUN, IL, IM )
	IF ( IL .EQ. 0 ) GOTO 900
	IF ( IL .GT. 0 ) GOTO 901
	IF ( IM .EQ. 0 ) GOTO 902

C*	Make sure the appropriate code/flag information has already been
C*	read into internal memory.

	IF ( CDMF .NE. 'Y' ) GOTO 903

	ITMP = IREADMT ( LUN )

C*	Check the validity of the input mnemonic(s).  Include special
C*	handling for originating centers, originating subcenters, data
C*	types and data subtypes, since those can be reported in
C*	Section 1 of a BUFR message as well as in Section 3, so if a
C*	user requests those mnemonics we can't necessarily assume they
C*	came from within Section 3.

	LCMG = LEN ( CMEANG )

	IF ( NEMOI(1:4) .EQ. 'GSES' ) THEN
	    IF ( ( NEMOD(1:6) .EQ. 'GCLONG' ) .OR.
     .		 ( NEMOD(1:4) .EQ. 'OGCE' ) .OR.
     .		 ( NEMOD(1:5) .EQ. 'ORIGC' ) )  THEN
		IFXYI = IFXY ( '001034' )
		IFXYD(1) = IFXY ( '001035' )
	    ELSE
		LNMNG = MIN ( 24, LCMG )
		IF ( LNMNG .EQ. 24 ) THEN
		    IRET = 3
		    CMEANG(1:24) = 'GCLONG  OGCE    ORIGC   '
		ELSE
		    IRET = -1
		END IF
		RETURN
	    END IF
	ELSE IF ( NEMOI(1:6) .EQ. 'GCLONG' ) THEN
	    IFXYI = IFXY ( '001031' )
	    IFXYD(1) = (-1)
	ELSE IF ( NEMOI(1:4) .EQ. 'OGCE' ) THEN
	    IFXYI = IFXY ( '001033' )
	    IFXYD(1) = (-1)
	ELSE IF ( NEMOI(1:5) .EQ. 'ORIGC' ) THEN
	    IFXYI = IFXY ( '001035' )
	    IFXYD(1) = (-1)
	ELSE IF ( ( NEMOI(1:7) .EQ. 'TABLASS' ) .OR.
     +		  ( NEMOI(1:7) .EQ. 'TABLASL' ) ) THEN
	    IF ( ( NEMOD(1:6) .EQ. 'TABLAT' ) ) THEN
		IF ( NEMOI(1:7) .EQ. 'TABLASS' ) THEN
		    IFXYI = IFXY ( '055021' )
		ELSE
		    IFXYI = IFXY ( '055022' )
		ENDIF
		IFXYD(1) = IFXY ( '055020' )
	    ELSE
		LNMNG = MIN ( 8, LCMG )
		IF ( LNMNG .EQ. 8 ) THEN
		    IRET = 1
		    CMEANG(1:8) = 'TABLAT  '
		ELSE
		    IRET = -1
		END IF
		RETURN
	    END IF
	ELSE IF ( NEMOI(1:6) .EQ. 'TABLAT' ) THEN
	    IFXYI = IFXY ( '055020' )
	    IFXYD(1) = (-1)
	ELSE
	    CALL PARSTR ( NEMOI, NEMO, 1, NTG, ' ', .TRUE. )
	    CALL NEMTAB ( LUN, NEMO, IFXYI, TAB, N )
	    IF ( ( N .EQ. 0 ) .OR. ( TAB .NE. 'B' ) ) GOTO 904
	    IF ( ( TABB ( N, LUN )(71:74) .NE. 'CODE' ) .AND.
     .		 ( TABB ( N, LUN )(71:74) .NE. 'FLAG' ) ) GOTO 905
	    IF ( NEMOD(1:1) .NE. ' ' ) THEN
		CALL PARSTR ( NEMOD, NEMO, 1, NTG, ' ', .TRUE. )
		CALL NEMTAB ( LUN, NEMO, IFXYD(1), TAB, N )
		IF ( ( N .EQ. 0 ) .OR. ( TAB .NE. 'B' ) ) GOTO 904
		IF ( ( TABB ( N, LUN )(71:74) .NE. 'CODE' ) .AND.
     .		     ( TABB ( N, LUN )(71:74) .NE. 'FLAG' ) ) GOTO 905
	    ELSE
	        IFXYD(1) = (-1)
	    END IF
	END IF

C*	Search the internal table for the requested meaning.

	CALL SRCHTBF ( IFXYI, IVALI, IFXYD, 10, IVALD,
     .		       CMEANG, LCMG, LNMNG, IRET )
	IF ( IRET .LE. 0 ) RETURN

C*	The meaning of this value is dependent on the value of another
C*	mnemonic in the report.

	IRET2 = IRET
	LNMNG = 0
	IRET = 0
	DO II = 1, IRET2
	    CALL NUMTBD ( LUN, IFXYD(II), NEMO, TAB, IERBD )
	    IF ( ( IERBD .GT. 0 ) .AND. ( TAB .EQ. 'B' ) .AND.
     .		   ( LCMG .GE. ( LNMNG + 8 ) ) ) THEN
		IRET = IRET + 1
		CMEANG(LNMNG+1:LNMNG+8) = NEMO
		LNMNG = LNMNG + 8
	    END IF
	END DO
	IF ( IRET .EQ. 0 ) IRET = -1

	RETURN
900     CALL BORT('BUFRLIB: GETCFMNG - INPUT BUFR FILE IS CLOSED, IT '//
     .   'MUST BE OPEN FOR INPUT')
901     CALL BORT('BUFRLIB: GETCFMNG - INPUT BUFR FILE IS OPEN FOR '//
     .   'OUTPUT, IT MUST BE OPEN FOR INPUT')
902     CALL BORT('BUFRLIB: GETCFMNG - A MESSAGE MUST BE OPEN IN '//
     .   'INPUT BUFR FILE, NONE ARE')
903     CALL BORT('BUFRLIB: GETCFMNG - TO USE THIS SUBROUTINE, MUST '//
     .   'FIRST CALL SUBROUTINE CODFLG WITH INPUT ARGUMENT SET TO Y')
904	WRITE(BORT_STR,'("BUFRLIB: GETCFMNG - MNEMONIC ",A,'//
     .   '" NOT FOUND IN TABLE B")') NEMO
	CALL BORT(BORT_STR)
905     WRITE(BORT_STR,'("BUFRLIB: GETCFMNG - MNEMONIC ",A,'//
     .   '" IS NOT A CODE OR FLAG TABLE")') NEMO
	CALL BORT(BORT_STR)
	END
